package untils

import (
	"fmt"
	"shop/common/global"
	"shop/common/model"
)

// SyncSeckillGoods 同步虚拟库存
func SyncSeckillGoods(seckillGoodsId, seckillStock int) error {
	key := fmt.Sprintf("seckill:stock%d", seckillGoodsId)
	for i := 0; i < seckillStock; i++ {
		err := global.Rdb.LPush(global.Ctx, key, i+1).Err()
		if err != nil {
			return err
		}
	}
	return nil
}

// UpdateSeckillGoodsStock 扣减秒杀库存
func UpdateSeckillGoodsStock(seckillGoodsId int) bool {
	key := fmt.Sprintf("seckill:stock%d", seckillGoodsId)
	_, err := global.Rdb.LPop(global.Ctx, key).Result()
	if err != nil {
		// 只有当Redis返回的错误是列表为空时，才认为是真正的库存不足
		// 其他情况下可能是Redis连接或其他错误
		if err.Error() == "redis: nil" {
			return false
		}
		// 对于其他Redis错误，记录日志但仍然返回false以保持系统稳定
		// 实际项目中应该添加日志记录
		return false
	}
	return true
}

// GetSeckillGoodsStock 获取秒杀商品虚拟库存
func GetSeckillGoodsStock(seckillGoodsId int) (int, error) {
	key := fmt.Sprintf("seckill:stock%d", seckillGoodsId)
	result, err := global.Rdb.LLen(global.Ctx, key).Result()
	if err != nil {
		return 0, err
	}
	return int(result), nil
}

// ReturnSeckillGoodsStock 返回商品秒杀虚拟库存
func ReturnSeckillGoodsStock(seckillGoodsId, num int) bool {
	key := fmt.Sprintf("seckill:stock%d", seckillGoodsId)
	for i := 0; i < num; i++ {
		_, err := global.Rdb.LPush(global.Ctx, key, 1).Result()
		if err != nil {
			return false
		}
	}
	return true
}

// ReturnAllSeckillGoodsStock 活动结束后返还所有未售出的秒杀虚拟库存到实际库存
func ReturnAllSeckillGoodsStock(seckillGoodsId int) (bool, error) {
	// 1. 获取Redis中剩余的虚拟库存数量
	key := fmt.Sprintf("seckill:stock%d", seckillGoodsId)
	remainingStock, err := global.Rdb.LLen(global.Ctx, key).Result()
	if err != nil {
		return false, fmt.Errorf("获取Redis虚拟库存失败: %v", err)
	}

	if remainingStock <= 0 {
		// 如果没有剩余库存，直接返回成功
		return true, nil
	}

	// 2. 开启事务，更新数据库中的库存
	tx := global.DB.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 3. 查询秒杀商品信息
	var seckillGood model.SeckillGoods
	if err := tx.Where("id = ?", seckillGoodsId).First(&seckillGood).Error; err != nil {
		tx.Rollback()
		return false, fmt.Errorf("查询秒杀商品失败: %v", err)
	}

	// 4. 查询关联的商品信息
	var goods model.Goods
	if err := tx.Where("id = ?", seckillGood.GoodId).First(&goods).Error; err != nil {
		tx.Rollback()
		return false, fmt.Errorf("查询商品信息失败: %v", err)
	}

	// 5. 计算需要返还的库存数量
	returnNum := int(remainingStock)

	// 6. 更新秒杀商品的库存（活动结束，将未售出的秒杀库存重置为0）
	if err := tx.Model(&model.SeckillGoods{}).
		Where("id = ?", seckillGoodsId).
		Update("seckill_stock", 0).Error; err != nil {
		tx.Rollback()
		return false, fmt.Errorf("更新秒杀商品库存失败: %v", err)
	}

	// 7. 将未售出的秒杀库存返还给原商品
	goods.GoodStock += int32(returnNum)
	if err := tx.Model(&goods).Update("good_stock", goods.GoodStock).Error; err != nil {
		tx.Rollback()
		return false, fmt.Errorf("更新商品库存失败: %v", err)
	}

	// 8. 提交事务
	if err := tx.Commit().Error; err != nil {
		tx.Rollback()
		return false, fmt.Errorf("事务提交失败: %v", err)
	}

	// 9. 清空Redis中的虚拟库存队列
	if _, err := global.Rdb.Del(global.Ctx, key).Result(); err != nil {
		// Redis删除失败不影响数据库事务结果，但记录日志
		return true, fmt.Errorf("清空Redis虚拟库存队列失败: %v", err)
	}
	return true, nil
}
